/*******************************************************************************
   @file    devio.c
   @author  H.M.Shim (elecage@gmail.com)
   @version
   @date    2013. 7. 25.
   @brief   디바이스 드라이버 관리자 구현파일.
   모든 디바이스 드라이버는 devInit, devOpen, devRead, devWrite,
 devIoctl, devClose 함수를 이용하여 제어한다. 각 디바이스 드라이버는 이 함수들에 매칭되는 각각의 함수를 작성해서
   등록한다. 만일 명령줄 입력을 사용할 경우 추가되는 함수를 사용한다. 명령줄 입력을 사용하기 위해서는 USE_CMDLINE이 정의되어야 한다.
  ******************************************************************************
  The MIT License (MIT)

Copyright (c) 2013 <copyright holders>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
  ******************************************************************************
  */


/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "devio.h"
#include "cmdline.h"
#include "dev_gpio.h"
#include "dev_i2c.h"
#include "dev_spi.h"
#include "dev_iueab.h"

/* Exported variables --------------------------------------------------------*/
/**
 * @defgroup	devioVariables	Device I/O variables
 * @{
 */
DeviceStructure deviceTable[MAX_DEV_NUMBER];
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
int32_t numberOfRegisteredDevice = 0;
/**
 * @}
 */
/* Private function prototypes -----------------------------------------------*/



/* Private functions ---------------------------------------------------------*/
/**
 * @defgroup devioFuncs Device I/O functions
 * @{
 */
/**
  * @brief   deviceIoInit()
  * @retval 0 : 성공
  */
int32_t deviceIoInit()
{
#ifdef USE_CMDLINE
	registerCmdline(DEV_CMD_OPEN, openCmd, DEV_HELP_OPEN);
	registerCmdline(DEV_CMD_READ1, readCmd, DEV_HELP_READ);
	registerCmdline(DEV_CMD_READ2, readCmd, DEV_HELP_READ);
	registerCmdline(DEV_CMD_WRITE1, writeCmd, DEV_HELP_WRITE);
	registerCmdline(DEV_CMD_WRITE2, writeCmd, DEV_HELP_WRITE);
	registerCmdline(DEV_CMD_CLOSE1, closeCmd, DEV_HELP_CLOSE);
	registerCmdline(DEV_CMD_CLOSE2, closeCmd, DEV_HELP_CLOSE);
	registerCmdline(DEV_CMD_IOCTL, ioctlCmd, DEV_HELP_IOCTL);
#endif /* USE_CMDLINE */
	deviceTable[0].dd = 0;
	deviceTable[0].devname = 0;

	registerDev_Gpio();
	registerDev_I2c();
	registerDev_Spi();
	registerDev_IuEab();
	return 0;
}

int32_t devOpen(const int8_t *devname, int32_t flags)
{
	DeviceStructure* device = deviceTable;
		while(device->dd != 0) {
			if(strcmp((const char*)device->devname, (const char*)devname) == 0) {
				return device->openFunc(devname, flags);
			}
			device++;
		}
		return DEV_ERR_UNREGISTERED_DEVICE;
}

ssize_t devWrite(int32_t dd, const void *buf, size_t n)
{
	DeviceStructure* device = deviceTable;
		while(device->dd != 0) {
			if(device->dd == dd) {
				return device->writeFunc(dd, buf, n);
			}
			device++;
		}
		return DEV_ERR_UNREGISTERED_DEVICE;
}

ssize_t devRead(int32_t dd, void *buf, size_t nbytes)
{
	DeviceStructure* device = deviceTable;
		while(device->dd != 0) {
			if(device->dd == dd) {
				return device->readFunc(dd, buf, nbytes);
			}
			device++;
		}
		return DEV_ERR_UNREGISTERED_DEVICE;
}
ssize_t devIoctl(int32_t dd, int32_t request, void* data)
{
	DeviceStructure* device = deviceTable;
		while(device->dd != 0) {
			if(device->dd == dd) {
				return device->ioctlFunc(dd, request, data);
			}
			device++;
		}
		return DEV_ERR_UNREGISTERED_DEVICE;
}
int32_t devClose(int dd)
{
	DeviceStructure* device = deviceTable;
		while(device->dd != 0) {
			if(device->dd == dd) {
				return device->closeFunc(dd);
			}
			device++;
		}
		return DEV_ERR_UNREGISTERED_DEVICE;
}

int32_t registerDevice(DeviceStructure device)
{
	deviceTable[numberOfRegisteredDevice].devname = device.devname;
	deviceTable[numberOfRegisteredDevice].dd = device.dd;
	deviceTable[numberOfRegisteredDevice].openFunc = device.openFunc;
	deviceTable[numberOfRegisteredDevice].readFunc = device.readFunc;
	deviceTable[numberOfRegisteredDevice].writeFunc = device.writeFunc;
	deviceTable[numberOfRegisteredDevice].ioctlFunc = device.ioctlFunc;
	deviceTable[numberOfRegisteredDevice].closeFunc = device.closeFunc;
#ifdef USE_CMDLINE
	deviceTable[numberOfRegisteredDevice].openCmdFunc = device.openCmdFunc;
	deviceTable[numberOfRegisteredDevice].readCmdFunc = device.readCmdFunc;
	deviceTable[numberOfRegisteredDevice].writeCmdFunc = device.writeCmdFunc;
	deviceTable[numberOfRegisteredDevice].ioctlCmdFunc = device.ioctlCmdFunc;
	deviceTable[numberOfRegisteredDevice].closeCmdFunc = device.closeCmdFunc;
#endif /* USE_CMDLINE */
	numberOfRegisteredDevice++;

	deviceTable[numberOfRegisteredDevice].devname = 0;
	deviceTable[numberOfRegisteredDevice].dd = 0;
	deviceTable[numberOfRegisteredDevice].openFunc = 0;
	deviceTable[numberOfRegisteredDevice].writeFunc = 0;
	deviceTable[numberOfRegisteredDevice].readFunc = 0;
	deviceTable[numberOfRegisteredDevice].ioctlFunc = 0;
	deviceTable[numberOfRegisteredDevice].closeFunc = 0;
#ifdef USE_CMDLINE
	deviceTable[numberOfRegisteredDevice].openCmdFunc = 0;
	deviceTable[numberOfRegisteredDevice].readCmdFunc = 0;
	deviceTable[numberOfRegisteredDevice].writeCmdFunc = 0;
	deviceTable[numberOfRegisteredDevice].ioctlCmdFunc = 0;
	deviceTable[numberOfRegisteredDevice].closeCmdFunc = 0;
#endif /* USE_CMDLINE */
	return 0;
}
#ifdef USE_CMDLINE


int32_t openCmd(int32_t argc, int8_t *argv[])
{
	if(argc < 2) {
		return CMDLINE_TOO_FEW_ARGS;
	}

	DeviceStructure* device = deviceTable;
	while(device->devname != 0) {
		if(strcmp((char*)device->devname, (char*)argv[1]) == 0) {
			return device->openCmdFunc(argc, argv);
		}
		device++;
	}

	return CMDLINE_BAD_CMD;
}

int32_t readCmd(int32_t argc, int8_t *argv[])
{
	if(argc < 2) {
		return CMDLINE_TOO_FEW_ARGS;
	}

	DeviceStructure* device = deviceTable;
	while(device->devname != 0) {
		if(strcmp((char*)device->devname, (char*) argv[1]) == 0) {
			return device->readCmdFunc(argc, argv);
		}
		device++;
	}

		return CMDLINE_BAD_CMD;
}
int32_t writeCmd(int32_t argc, int8_t *argv[])
{
	if(argc < 2) {
		return CMDLINE_TOO_FEW_ARGS;
	}
	DeviceStructure* device = deviceTable;
	while(device->devname != 0) {
		if(strcmp((char*)device->devname, (char*)argv[1]) == 0) {
			return device->writeCmdFunc(argc, argv);
		}
		device++;
	}

	return CMDLINE_BAD_CMD;
}

int32_t ioctlCmd(int32_t argc, int8_t *argv[])
{
	if(argc < 2) {
		return CMDLINE_TOO_FEW_ARGS;
	}

	DeviceStructure* device = deviceTable;
	while(device->devname != 0) {
		if(strcmp((char*)device->devname, (char*)argv[1]) == 0) {
			return device->ioctlCmdFunc(argc, argv);
		}
		device++;
	}

	return CMDLINE_BAD_CMD;
}

int32_t closeCmd(int32_t argc, int8_t *argv[])
{
	if(argc < 2) {
		return CMDLINE_TOO_FEW_ARGS;
	}

	DeviceStructure* device = deviceTable;
	while(device->devname != 0) {
		if(strcmp((char*)device->devname, (char*)argv[1]) == 0) {
			return device->closeCmdFunc(argc, argv);
		}
		device++;
	}
	return CMDLINE_BAD_CMD;
}
#endif /* USE_CMDLINE */
/**
 * @}
 */
